import time

from PySide2 import QtWidgets
from PySide2.QtGui import QIcon

import share
from binding import mapping_detail_bind
from PySide2.QtWidgets import QHeaderView, QTableWidgetItem, QPushButton, QHBoxLayout, QWidget, QMessageBox, \
    QAbstractItemView, QTableView, QApplication
import json
import requests

from elementUI.freezeTableWidget import masking_element
from util.TableWidgetUtil import TableWidgetUtil
from util.requestUtil import requestUtil


class bind:
    def __init__(self):

        self.ui = share.SI.main.ui
        self.mui = share.SI.mapping.ui

    def incident(self):

        # 映射源数据单元格平铺表格
        self.mui.original_mapping_tableWidget.setHorizontalHeaderLabels(['编号', '数据源', '版本'])
        self.mui.original_mapping_tableWidget.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.mui.original_mapping_tableWidget.setSelectionMode(QAbstractItemView.SingleSelection)
        self.mui.original_mapping_tableWidget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.mui.original_mapping_tableWidget.horizontalHeader().setStyleSheet(
            "QHeaderView::section {background-color:#06193D;color: #ffffff;padding-left: 4px;border: 1px solid #6c6c6c;}")

        # 映射模板单元格平铺表格
        self.mui.template_mapping_tableWidget.setHorizontalHeaderLabels(['编号', '模板数据'])
        self.mui.template_mapping_tableWidget.setSelectionBehavior(QAbstractItemView.SelectRows)
        self.mui.template_mapping_tableWidget.setSelectionMode(QAbstractItemView.SingleSelection)
        self.mui.template_mapping_tableWidget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.mui.template_mapping_tableWidget.horizontalHeader().setStyleSheet(
            "QHeaderView::section {background-color:#06193D;color: #ffffff;padding-left: 4px;border: 1px solid #6c6c6c;}")

        self.mui.template_mapping_tableWidget.itemClicked.connect(self.get_T_row)

        # 创建映射关系
        self.ui.create_mapping_button.clicked.connect(lambda: self.create_mapping())
        self.ui.create_mapping_button.setIcon(QIcon("./static/img/新建.png"))
        # 查询映射
        self.ui.mapping_select_button.clicked.connect(lambda: self.findMapping())
        self.ui.mapping_select_button.setIcon(QIcon("./static/img/查询.png"))
        # 映射确认
        self.mui.mapping_affirm_button.clicked.connect(lambda: self.mapping_affirm_fun())

    def get_T_row(self):
        name = self.mui.template_mapping_tableWidget.selectedItems()[0].text()
        # 创建名称，如果有.xls则去.xls,有空格去空格，有括号去括号
        if '.' in name:
            name = name.split('.')[0]

        name = name.replace(' ', '').replace('(', '').replace(')', '').replace('（', '').replace('）', '')
        # 将名称填至表名框
        self.mui.table_name.setPlainText(name)

    def create_mapping(self):

        # 获取查询条件
        origin_name = self.mui.origin_select_lineEdit.text() if self.mui.origin_select_lineEdit.text() != "" else "None"
        # 查询分组及单位
        from binding.home_bind import home_bind
        ug = home_bind().get_ug_comboBox_fun()
        template_name = self.mui.template_select_lineEdit.text() if self.mui.template_select_lineEdit.text() != "" else "None"

        # 获取源数据头列表
        original_dataList = requestUtil("/original/" + origin_name,"GET").dataMap['data']
        # 获取模板头列表
        template_dataList = requestUtil("/template/findByGroup/" + ug["group_value"] + "/" + ug["unit_value"] + "/" + template_name,"GET").dataMap['data']

        # 渲染数据
        TableWidgetUtil().render(self.mui.original_mapping_tableWidget,original_dataList,[{"key":"id","value":"id"},{"key":"编码","value":"code"},{"key":"名称","value":"name"},{"key":"版本","value":"version"}])
        TableWidgetUtil().render(self.mui.template_mapping_tableWidget,template_dataList,[{"key":"id","value":"id"},{"key":"名称","value":"name"}])
        TableWidgetUtil().head_color_show(self.mui.original_mapping_tableWidget,q=False)
        TableWidgetUtil().head_color_show(self.mui.template_mapping_tableWidget,q=False)
        self.mui.original_mapping_tableWidget.hideColumn(0)
        self.mui.template_mapping_tableWidget.hideColumn(0)
        share.jq.mapping_check_flag = 1
        self.mui.show()

    # 确认映射
    def mapping_affirm_fun(self):
        self.mui.original_mapping_tableWidget.showColumn(0)
        self.mui.template_mapping_tableWidget.showColumn(0)
        templateRow = self.mui.template_mapping_tableWidget.selectedItems()[0].text()
        originalRow = self.mui.original_mapping_tableWidget.selectedItems()[0].text()
        self.mui.original_mapping_tableWidget.hideColumn(0)
        self.mui.template_mapping_tableWidget.hideColumn(0)
        table_name = self.mui.table_name.toPlainText()

        if share.jq.mapping_check_flag == 1:
            url = share.RURL.backendUrl + "/mapping/create/" + originalRow + "/" + templateRow + "/" + table_name
        else:
            url = share.RURL.backendUrl + "/mapping/create1/" + originalRow + "/" + templateRow + "/" + table_name

        requests.encoding = 'utf-8'
        result = requests.request(method="GET", url=url, headers=share.token.headers)
        dataMap = json.loads(result.text)
        try:
            if dataMap["flag"] == True:
                QtWidgets.QMessageBox.about(self.ui.original_tableWidget, "信息提示框", dataMap["message"])
                # 查询头元数据列表
                self.findMapping()
        except:
            QtWidgets.QMessageBox.about(self.ui.original_tableWidget, "信息提示框", "新增映射失败")

    # 查询映射组信息
    def findMapping(self):
        # 查询分组及单位
        from binding.home_bind import home_bind
        ug = home_bind().get_ug_comboBox_fun()
        name = self.ui.mapping_select_lineEdit.text() if self.ui.mapping_select_lineEdit.text() != "" else "None"
        dataMap = requestUtil("/mapping/findByGroup/" + ug["group_value"] + "/" + ug["unit_value"] + "/" + name, "GET").dataMap

        for index, item in enumerate(dataMap["data"]):
            item["buttons"] = self.buttonForRow(item["id"], item["oname"], item["tname"])
        dataList = dataMap['data']
        # 准备表头数据
        head_list = [{'key': "映射名称", "value": "tableName"}, {'key': "源数据", "value": "oname"},
                     {'key': "源数据版本", "value": "version"}, {'key': "模板数据", "value": "tname"},{'key': "分组", "value": "gname"},{'key': "单位", "value": "uname"},
                     {'key': "操作", "value": "buttons"}]
        TableWidgetUtil().render(self.ui.mapping_tableWidget, dataList, head_list)
        TableWidgetUtil().head_color_show(self.ui.mapping_tableWidget)

    # output
    def output(self,id,name):
        OutPut(id,name).start()



    # flag = True 开启编辑组
    def alter_template(self, id, name, tableName,flag):

        masking = masking_element()
        masking.mpShadeWindow.show()
        QApplication.processEvents()

        if flag == True:
            self.ui.fx_widget.show()
            # 公式框内容清空
            self.ui.formula_compile.clear()
        else:
            self.ui.fx_widget.hide()

        # 设置公式编辑表头
        self.ui.fx_lable.setText(tableName)
        if "科目余额" in name:
            # 科目余额表赋值
            mapping_detail_bind.data_bind(id).BData_KM()
            self.ui.mapping_original_border_widget.findChild(QTableView, "mapping_original_tableView").show()
            self.ui.mapping_original_border_widget.findChild(QTableView, "mapping_original_XJ_tableView").hide()
        else:
            mapping_detail_bind.data_bind(id).BData_XJ()
            self.ui.mapping_original_border_widget.findChild(QTableView, "mapping_original_tableView").hide()
            self.ui.mapping_original_border_widget.findChild(QTableView, "mapping_original_XJ_tableView").show()
        # 跳转至公式编辑页
        self.ui.stackedWidget.setCurrentIndex(5)
        masking.mpShadeWindow.hide()

    # 删除映射组
    def del_template(self, id):

        A = QMessageBox.question(self.ui.template_tableWidget, '确认', '是否删除该映射?', QMessageBox.Yes | QMessageBox.No)

        if A == QMessageBox.No:
            return

        url = share.RURL.backendUrl + "/mapping/del/" + str(id)
        requests.encoding = 'utf-8'
        result = requests.request(method="GET", url=url, headers=share.token.headers)
        dataMap = json.loads(result.text)

        try:
            if dataMap["flag"] == True:
                QtWidgets.QMessageBox.about(self.ui.original_tableWidget, "信息提示框", dataMap["message"])
                # 查询头元数据列表
                self.findMapping()
        except:
            QtWidgets.QMessageBox.about(self.ui.original_tableWidget, "信息提示框", "删除失败")

    # 列表内添加按钮
    def buttonForRow(self, id, name, tname):
        widget = QWidget()

        # 查看
        checkBtn = QPushButton('输出')
        checkBtn.setStyleSheet(''' QPushButton{
                                    text-align : center;
                                    background-color : transparent;
                                    height : 30px;
                                    width:40px;
                                    border-style: outset;
                                    color:#192D9E;
                                    }
                                     
                                    QPushButton:hover{
                                    	color: #192D9E;
                                    	text-decoration:underline;
                                    }''')


        # 修改
        alterBtn = QPushButton('修改')
        alterBtn.setStyleSheet(''' QPushButton{
                                    text-align : center;
                                    background-color : transparent;
                                    height : 30px;
                                    width:40px;
                                    border-style: outset;
                                    color:#192D9E;
                                    }
                                     
                                    QPushButton:hover{
                                    	color: #192D9E;
                                    	text-decoration:underline;
                                    }''')

        # 删除
        deleteBtn = QPushButton('删除')
        deleteBtn.setStyleSheet(''' QPushButton{
                                    text-align : center;
                                    background-color : transparent;
                                    height : 30px;
                                    width:40px;
                                    border-style: outset;
                                    color:red;}
                                     
                                    QPushButton:hover{
                                    	color: red;
                                    	text-decoration:underline;
                                    }''')

        checkBtn.clicked.connect(lambda: self.output(id, name))
        alterBtn.clicked.connect(lambda: self.alter_template(id, name, tname,True))
        deleteBtn.clicked.connect(lambda: self.del_template(id))

        hLayout = QHBoxLayout()
        hLayout.addWidget(checkBtn)
        hLayout.addWidget(alterBtn)
        hLayout.addWidget(deleteBtn)
        hLayout.setContentsMargins(5, 2, 5, 2)
        widget.setLayout(hLayout)
        return widget

class OutPut:
    def __init__(self,id,name):
        self.id = id
        self.name = name
    def start(self):

        # 查询映射信息
        request = requestUtil("/mapping/" + str(self.id), "GET")
        dataMap = request.dataMap['data']
        # 拉取源数据(根据组织，原表类型以及版本查询源数据)
        sort = dataMap["ogroupID"]
        request = requestUtil("/original/findBySort/" + str(sort), "GET")
        OdataList = request.dataMap['data']['originalList']
        period = request.dataMap['data']['original']['period']
        # 拉取模板数据
        tid = dataMap["tid"]
        request = requestUtil("/template/findByPid/" + str(tid), "GET")
        TdataList = request.dataMap['data']

        # 预备向久其表中插入的数据
        data_ready= []

        tdataDataList = []
        # 遍历模板数据，筛选公式
        for index1 in range(len(TdataList)):
            print(index1)
            TRow = json.loads(TdataList[index1]['data'],strict=False)     #获取模板行数据
            tdataDataList.append(TRow)
            for TRowIndex in range(len(TRow)):              #遍历行数据
                if str(TRow[TRowIndex]).startswith('[') and str(TRow[TRowIndex]).endswith(']') and "," in str(TRow[TRowIndex]):      #检查当前单元格内数据是否是公式
                    try:
                        value = self.analysis(OdataList,TRow[TRowIndex])
                        if not (value == 'f'):
                            TRow[TRowIndex] = [str(index1+1) + "-" + str(TRowIndex+1),value]
                            data_ready.append(TRow[TRowIndex])
                    except Exception as e:
                        print(e)
                        QtWidgets.QMessageBox.about(share.SI.main.ui ,"信息提示框",dataMap['tableName'] + ":" + str(index1+1) + "行" + str(TRowIndex+1) + "列公式错误");
                        return False

        for index,item in enumerate(data_ready):
            xy = item[0].split("-")
            tdataDataList[int(xy[0])-1][int(xy[1])-1] = item[1]

        fname = dataMap["tableName"]+str(time.time())
        # 查询分组及单位
        from binding.home_bind import home_bind
        ug = home_bind().get_ug_comboBox_fun()
        url = share.RURL.backendUrl + "/template/outPut/" + ug["group_value"] + "/" + ug["unit_value"] + "/" + fname + "/" + str(period) + "/" + str(dataMap["tid"])

        result = requests.request(method="POST", url=url,json=tdataDataList, verify=False, headers=share.token.headers)
        dataMap = json.loads(result.text)
        if "flag" in dataMap.keys():
            QtWidgets.QMessageBox.about(share.SI.main.ui, "信息提示框", dataMap["message"])
        else:
            QtWidgets.QMessageBox.about(share.SI.main.ui ,"添加失败", dataMap["message"])


        # 公式解析
    # ODataList源数据列表
    # TFormula待解析公式
    def analysis(self,ODataList,TFormula):

        formula = None

        if "&" in TFormula:             #判断是否是分项公式
            TG = TFormula[1:len(TFormula)-1]            #公式去边
            formulaList = TG.split("&")
            for fl in formulaList:
                if share.jq.organization in fl:
                    # 解公式
                    formula = fl.split(":")[1][:-1]
                    break
                else:
                    formula = 0

        else:
            if ":{" in TFormula:
                if share.jq.organization in TFormula:
                    formula = TFormula[1:len(TFormula)-2].split(":")[1]
            else:
                formula = TFormula[1:len(TFormula)-1]

        # 如果公式内不包括当前公司则返回空
        if formula == 0 or formula == "" or formula == None:
            return 'f'

        # 解if
        if 'if' in formula:
            startIndex = formula.find('if')
            endIndex = formula.find('then')
            check = formula[startIndex+2:endIndex]
            checkBuffer = self.node_analysis(check,ODataList)
            for index in range(len(checkBuffer)):
                if checkBuffer[index][0] != " ":
                    check = check.replace(checkBuffer[index][0],checkBuffer[index][1])
            check = check.replace("{","").replace("[","").replace("}","").replace("]","").replace(",","")

            # 解析if成功，选择公式
            formulaList = formula.split("else")
            if eval(check):
                formula = formulaList[0].split("then")[1]
            else:
                formula = formulaList[1].replace(">","")

        TBuffer = self.node_analysis(formula,ODataList)

        # TBuffer是公式和实际值的集合，以下步骤是将公式替换为实际值
        for index in range(len(TBuffer)):
            if TBuffer[index][0] != " " and  TBuffer[index][0] != "(":
                formula = formula.replace(TBuffer[index][0],TBuffer[index][1])
        formula = formula.replace("{","").replace("[","").replace("}","").replace("]","").replace(",","").replace(">","").replace("<","")

        return eval(formula)

    # 真实公式处理
    def node_analysis(self,TFormula,ODataList):
        TGONE = TFormula.split("{")
        for index in range(len(TGONE)):
            try:
                if TGONE[index].__contains__('}'):
                    TGONE[index] = TGONE[index][0:TGONE[index].rfind("}")]
                else:
                    pass
            except:
                pass

        # 经过上步的处理，数组中还有许多废料，以下进行进一步加工和公式实际值的查询

        data_last = []
        for index in range(len(TGONE)):
            if TGONE[index] != '' and TGONE[index] != '-' and  not('abs(' in TGONE[index]):
                data_last.append([TGONE[index],self.find(TGONE[index],ODataList)])

        return data_last

    # 根据公式查询实际数据
    def find(self,TFormula,ODataList):

        TKeyValue = TFormula.rsplit(',', 1)

        for index in range(len(ODataList)):
            dataRow = json.loads(ODataList[index]['data'],strict=False)
            OKey2 = str(dataRow[0]) + dataRow[1]         # 前两列
            if len(dataRow) > 5:
                OKey5 = str(dataRow[0]) + str(dataRow[1]) + str(dataRow[2]) + str(dataRow[3]) + str(dataRow[4])        # 前五列

            else:
                OKey5 = "----------"
            if TKeyValue[0] == OKey5:
                return dataRow[int(TKeyValue[1]) - 2] if dataRow[int(TKeyValue[1]) - 2] != "" and dataRow[int(TKeyValue[1]) - 2] != None and dataRow[int(TKeyValue[1]) - 2] != 'None' else "0"
            elif OKey2 != "" and (OKey2 in TKeyValue[0] and dataRow[2] in TKeyValue[0]) or str(dataRow[0]) == TKeyValue[0]:
                return dataRow[int(TKeyValue[1]) - 2] if dataRow[int(TKeyValue[1]) - 2] != "" and dataRow[int(TKeyValue[1]) - 2] != None and dataRow[int(TKeyValue[1]) - 2] != 'None' else "0"
            elif str(dataRow[0]) in TKeyValue[0]:
                if self.is_number(dataRow[1]):
                    return dataRow[int(TKeyValue[1]) - 2] if dataRow[int(TKeyValue[1]) - 2] != "" and dataRow[int(TKeyValue[1]) - 2] != None and dataRow[int(TKeyValue[1]) - 2] != 'None' else "0"

        return "0"

    # 判断字符串是否是数字
    def is_number(self,target_str):
        try:
            float(target_str)
            return True
        except:
            pass
        if target_str.isnumeric():
            return True
        return False